<?php
namespace app\api\service\delivery\dada;

use app\api\model\Shop;
use app\api\service\delivery\PlatformInterface;
use app\api\service\delivery\dada\ApiService;
use think\exception\ValidateException;
use app\api\model\SenderInfo;
use app\api\model\ReceiverInfo;
use app\api\model\OrderDada;
use app\api\model\Order;
use app\api\model\Courier;
use think\facade\Log;
use think\facade\Db;
use app\api\model\MallDealLog;
use app\api\model\AppConfig;

// 达达
class DadaAdapter implements PlatformInterface
{

    public $ApiService;
    protected $config;//配置

    //region 状态码

    // 达达状态码
    const STATUS_ERROR = 'fail';//失败
    const STATUS_SUCCESS = 'success';//成功

    public static function statusList()
    {
        return [
            self::STATUS_ERROR => 'error',
            self::STATUS_SUCCESS => 'Success',
        ];
    }

    // 达达状态码
    const DADA_STATUS_ERROR = 'fail';//失败
    const DADA_STATUS_SUCCESS = 'ok';//成功

    public static function dadaStatusList()
    {
        return [
            self::DADA_STATUS_ERROR => 'error',
            self::DADA_STATUS_SUCCESS => 'Success',
        ];
    }

    // 达达订单状态
    const DD_STATUS_ORDER_DISPATCH = 1;
    const DD_STATUS_ORDER_PICKUPING = 2;
    const DD_STATUS_ORDER_DELIVERY = 3;
    const DD_STATUS_ORDER_COMPLETED = 4;
    const DD_STATUS_ORDER_CANCELLED = 5;

    const DD_STATUS_ORDER_ASSIGN = 8;
    const DD_STATUS_ORDER_ABNORMAL_MIDWAY = 9;
    const DD_STATUS_ORDER_ABNORMAL_COMPLETED = 10;
    const DD_STATUS_ORDER_REACH = 100;
    const DD_STATUS_ORDER_ERROR = 1000;

    public static function statusDdOrderList()
    {
        return [
            self::DD_STATUS_ORDER_DISPATCH => '待接单',
            self::DD_STATUS_ORDER_PICKUPING => '待取货',
            self::DD_STATUS_ORDER_DELIVERY => '配送中',
            self::DD_STATUS_ORDER_COMPLETED => '已完成',
            self::DD_STATUS_ORDER_CANCELLED => '已取消',

            self::DD_STATUS_ORDER_ASSIGN => '指派单',
            self::DD_STATUS_ORDER_ABNORMAL_MIDWAY => '妥投异常之物品返回中',
            self::DD_STATUS_ORDER_ABNORMAL_COMPLETED => '妥投异常之物品返回完成',
            self::DD_STATUS_ORDER_REACH=> '骑士到店',
            self::DD_STATUS_ORDER_ERROR => '创建达达运单失败',
        ];
    }

    // 总表订单状态
    const STATUS_ORDER_DISPATCH = 20;//派单中（转单改派中）
    const STATUS_ORDER_PICKUPING = 30;//待取货(已就位）
    const STATUS_ORDER_DELIVERY = 40;//闪送中(申请取消中、物品送回中、取消单客服介入中）
    const STATUS_ORDER_COMPLETED = 50;//已完成（已退款）
    const STATUS_ORDER_CANCELLED = 60;//已取消

    public static function statusOrderList()
    {
        return [
            self::STATUS_ORDER_DISPATCH => '派单中',
            self::STATUS_ORDER_PICKUPING => '待取货',
            self::STATUS_ORDER_DELIVERY => '配送中',
            self::STATUS_ORDER_COMPLETED => '已完成',
            self::STATUS_ORDER_CANCELLED => '已取消',
        ];
    }
//endregion
    /*
    * $config: 配置信息
    * $pro_dev: true正式域名 false测试域名
    */
    public function __construct(array $config)
    {
        $this->config = $config;
        $this->ApiService=new ApiService($config);
    }

// ------------------------------------具体实现方法-----------------------------------



    // 1.查询开通城市
    public function openCitiesLists($params=[])
    {
        $res = $this->ApiService->sendUnite('openCitiesLists','');

        return $this->ApiService->returnUnite($res);
    }

    //达达商家注册
    public function registerMerchant($params=[])
    {

        //region 校验商家注册传入参数
        try {
            validate([
                'mobile'  => 'require',
                'cityName'  => 'require',
                'enterpriseName'  => 'require',
                'enterpriseAddress'  => 'require',
                'contactName'  => 'require',
                'contactPhone'  => 'require',
                'email'  => 'require',
            ])->message([
                'mobile.require'  => '注册手机号为空',
                'cityName.require'  => '商户城市名称为空',
                'enterpriseName.require'  => '商户名称为空',
                'enterpriseAddress.require'  => '商户地址为空',
                'contactName.require'  => '联系人姓名为空',
                'contactPhone.require'  => '联系人电话为空',
                'email.require'  => '联系人邮箱为空',
            ])->check($params);
        }catch (ValidateException $e){
            output_error($e->getError());}
        //endregion

        //region 组装商家注册参数，并调用达达注册
        $data['mobile']=$params['mobile'];
        $data['city_name']=$params['cityName'];
        $data['enterprise_name']=$params['enterpriseName'];
        $data['enterprise_address']=$params['enterpriseAddress'];
        $data['contact_name']=$params['contactName'];
        $data['contact_phone']=$params['contactPhone'];
        $data['email']=$params['email'];
        $data['source_id']='';

        $res = $this->ApiService->sendUnite('registerMerchant',$data);
        return $this->ApiService->returnUnite($res);
        //endregion
    }

    //店铺新增 修改
    public function storeOperation($params=[])
    {
        //region 校验店铺新增修改参数
        try {
            validate([
                'storeName'  => 'require',
                'address'  => 'require',
                'latitude'  => 'require',
                'longitude'  => 'require',
                'contactName'  => 'require',
                'phone'  => 'require',
                'business'  => 'require',
                'operationType'  => 'require',
                'platformStoreId'  => 'require',
            ])->message([
                'storeName.require'  => '门店名称必须传递',
                'address.require'  => '门店地址必须传递',
                'latitude.require'  => '门店地址维度必须传递',
                'longitude.require'  => '门店地址经度必须传递',
                'contactName.require'  => '联系人姓名必须传递',
                'phone.require'  => '联系人电话必须传递',
                'business.require'  => '物品类目必须传递',
                'operationType.require'  => '操作方式必须传递',
                'platformStoreId.require'  => '店铺唯一标识必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            output_error($e->getError());
        }
        //endregion

        // 默认值为1创建店铺，2更新店铺
        $dist['type'] = $params['operationType'];

        if ($dist['type'] == 1) {//新增店铺时，如果有，直接返回
            $whereShop['appid']=$params['appid'];
            $whereShop['platform_store_id']=$params['platformStoreId'];
            $whereShop['app_type']=$params['app_type'];
            $find_shop=Shop::where($whereShop)->find();
            if($find_shop){
                $retDate['storeId']=$find_shop['store_id'];
                return result_success('success',$retDate);
            }
        }

        //region 构造店铺新增修改 调用达达参数
        $apiData['station_name'] = $params['storeName'];
        $apiData['station_address'] = $params['addressDetail'];
        $apiData['contact_name'] = $params['contactName'];
        $apiData['business'] = $params['business'];
        $apiData['lng'] = $params['longitude'];
        $apiData['phone'] = $params['phone'];
        $apiData['lat'] = $params['latitude'];

        //endregion

        // region 构造店铺新增修改落地参数
        $data['appid'] =  $params['appid'];
        $data['app_type'] = get_app_type_int($params['app_type']);
        $data['store_name'] = $params['storeName'];
        $data['contact_name'] = $params['contactName'];
        $data['city_name'] = $params['cityName'];
        $data['address'] = $params['address'];
        $data['address_detail'] = $params['addressDetail'];
        $data['latitude'] = $params['latitude'];
        $data['longitude'] = $params['longitude'];
        $data['phone'] = $params['phone'];
        $data['good_type'] = $params['business'];
        $data['platform_store_id'] =  $params['platformStoreId'];
        //endregion

        //修改店铺需要传递店铺ID
        if ($dist['type'] == 2) {
            if (empty($params['storeId'])) {
                output_error('更新店铺时店铺ID不能为空');
            }
            $dist['method'] = 'modifyStore';
            // 修改店铺必传店铺ID
            $apiData['origin_shop_id'] = $data['store_id'] = $params['storeId'];
            $apiData = json_encode(array_filter($apiData));
        }else{
            $dist['method']='addStores';
            $apiData =json_encode([array_filter($apiData)]);
        }

        Log::info('达达--店铺操作--请求参数---:' . json_encode($apiData));
        $resApi = $this->ApiService->sendUnite($dist['method'],$apiData);
        Log::info('达达--店铺操作--请求结果---:' . json_encode($resApi));

        //region 处理返回值
        if(isset($resApi['status'])&&$resApi['status']==self::STATUS_SUCCESS){
            if ($dist['type'] == 1){
                //新增
                $Order = new Shop();
                $data['store_id'] = $resApi['result']['successList'][0]['originShopId'];
                $data['pro_dev'] = get_pro_dev_int($params['app_type']);
                $add = $Order->shopCreate($data);

            }else{
                //修改
                $Order = new Shop();
                $add = $Order->shopUpdate($data);
            }

            if($add['success']){
                $retDate['storeId']=$data['store_id'];
                return result_success('success',$retDate);
            }else{
                return result_error($add["msg"]??'保存失败');
            }
        }else{
            return result_error($resApi['msg']??"请求失败");
            // return result_error($resApi['msg']."，《".$resApi['result']['failedList'][0]['shopName'].'》'.$resApi['result']['failedList'][0]['msg']??'请求创建门店失败！');
        }
        //endregion
    }

    //订单取消原因
    public function cancelReasons($params=[])
    {
        $dist['method']='cancelReasons';
        $res = $this->ApiService->sendUnite($dist['method'],'');
        return $this->ApiService->returnUnite($res);
    }

    //商家投诉
    public function complaint($params=[])
    {
        //region 校验参数
        try {
            validate([
                'order_id'  => 'require',
                'reasonId'  => 'require',
            ])->message([
                'order_id.require'  => '订单号必须传递',
                'order_id.require'  => '投诉原因必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            output_error($e->getError());
        }
        //endregion

        $apiData['order_id']=$params['order_id'];
        $apiData['reason_id']=$params['reasonId'];
        $dist['method']='complaint';
        $apiData = json_encode(array_filter($apiData));
        Log::info('达达--商家投诉--请求参数---:' . json_encode($apiData));
        $resApi = $this->ApiService->sendUnite($dist['method'],$apiData);
        Log::info('达达--商家投诉--请求结果---:' . json_encode($resApi));
        return $this->ApiService->returnUnite($resApi);
    }

    //商家投诉原因
    public function complaintReasons($params=[])
    {
        $dist['method']='complaintReasons';
        $res = $this->ApiService->sendUnite($dist['method'],'');
        return $this->ApiService->returnUnite($res);
    }

    // 新增店铺(可批量)
    public function addStores($params=[])
    {
        return result_error("达达不支持");
    }

    // 分页查询商户店铺
    public function queryAllStores($params=[])
    {
        //region 校验查询参数
        try {
            validate([
                'storeId'  => 'require'
            ])->message([
                'storeId.require'  => '门店编号必须传递'
            ])->check($params);
        } catch (ValidateException $e) {
            output_error($e->getError());
        }
        //endregion

        //region 构造店铺查询 调用达达参数
        $apiData['origin_shop_id']=$params['storeId'];
        $dist['method']='queryAllStores';
        $apiData = json_encode(array_filter($apiData));

        Log::info('达达--店铺查询--请求参数---:' . json_encode($apiData));
        $resApi = $this->ApiService->sendUnite($dist['method'],$apiData);
        Log::info('达达--店铺查询--请求结果---:' . json_encode($resApi));
        //endregion

        //region 处理返回值
        if(isset($resApi['status'])&&$resApi['status']==self::STATUS_SUCCESS){
            // region 处理返回值
            $resApi['data']['storeId'] = $resApi['result']['origin_shop_id'];
            $resApi['data']['storeName'] = $resApi['result']['station_name'];
            $resApi['data']['contactsMobile'] = $resApi['result']['phone'];
            $resApi['data']['cityName'] = $resApi['result']['city_name'];
            $resApi['data']['address'] = $resApi['result']['station_address'];
            $resApi['data']['addressDetail'] = $resApi['result']['station_address'];
            $resApi['data']['latitude'] = $resApi['result']['lat'];
            $resApi['data']['longitude'] = $resApi['result']['lng'];
            $resApi['data']['status'] = $resApi['result']['status'];
            //endregion

            return result_success('success',[$resApi['data']]);
        }
        else{
            return result_error($resApi['msg']??"请求失败");
        }
    }

    // 查询城市可指定的交通工具
    public function optionalTravelWay($params=[])
    {
        return result_error("达达不支持");
    }

    // 订单计费（查询运费）
    public function orderCalculate($params=[])
    {
        \think\facade\Log::info('闪送--订单计费--请求源参数--:' . json_encode($params));

        try {
            validate([
                'sender'  => 'require', 
                'receiverList'  => 'require', 
                'storeId'  => 'require', 
                'callNumber'  => 'require', 
            ])->message([ 
                'sender.require'  => 'sender必须传递',   
                'receiverList.require'  => 'receiverList必须传递',   
                'storeId.require'  => 'storeId必须传递',   
                'callNumber.require'  => 'callNumber必须传递',   
            ])->check($params);
        } catch (ValidateException $e) {
            output_error($e->getError());
        }

        // 达达下单参数说明
        // $postData['shop_no'] =  $params['shop_no'] ;//门店编号
        // $postData['origin_id'] =  $params['origin_id'] ;//调用方单号
        // $postData['cargo_price'] =  $params['cargo_price'] ;//订单金额
        // $postData['is_prepay'] =  $params['is_prepay'] ;//是否需要垫付 1:是 0:否 (垫付订单金额，非运费)
        // $postData['receiver_name'] =  $params['receiver_name'] ;//收货人姓名
        // $postData['receiver_address'] =  $params['receiver_address'] ;//收货人地址
        // $postData['callback'] =  $params['callback'] ;//回调URL
        // $postData['cargo_weight'] =  $params['cargo_weight'] ;//订单重量（单位：Kg）
        // $postData['receiver_lat'] =  $params['receiver_lat'] ;//收货人地址纬度
        // $postData['receiver_lng'] =  $params['receiver_lng'] ;//收货人地址经度
        // $postData['receiver_phone'] =  $params['receiver_phone'] ;//收货人手机号（手机号和座机号必填一项）
        // $postData['receiver_tel'] =  $params['receiver_tel'] ;//收货人座机号（手机号和座机号必填一项）

        // $postData['tips'] =  $params['tips'] ;//小费（单位：元，精确小数点后一位，小费金额不能高于订单金额。）
        // $postData['info'] =  $params['info'] ;//订单备注
        // $postData['cargo_type'] =  $params['cargo_type'] ;//物品品类
        // $postData['cargo_num'] =  $params['cargo_num'] ;//订单商品数量
        // $postData['origin_mark'] =  $params['origin_mark'] ;//订单来源标识（支持传汉字、字母，最大长度为10），请传入和小票相同的订单来源名称，避免骑士取错货；除以下已定义枚举值，如需自定义请联系业务经理开通。传参：在骑士APP展示内容elm：饿了么mt：美团外卖jdwl：京东物流
        // $postData['origin_mark_no'] =  $params['origin_mark_no'] ;//订单来源编号（支持数字、字母，最大长度为30），该字段会和origin_mark组合展示给骑士；示例：origin_mark传"mt"，origin_mark_no传"001"，则给骑士展示"美团外卖#001"
        // $postData['is_use_insurance'] =  $params['is_use_insurance'] ;//是否使用保价费（0：不使用保价，1：使用保价； 同时，请确保填写了订单金额（cargo_price））
        // $postData['is_finish_code_needed'] =  $params['is_finish_code_needed'] ;//收货码（0：不需要；1：需要。收货码的作用是：骑手必须输入收货码才能完成订单妥投）
        // $postData['delay_publish_time'] =  $params['delay_publish_time'] ;//	预约发单时间（unix时间戳(10位)，精确到分），可以支持未来3天内的订单发预约单，如预约发单时间早于当前时间会作为即时单下发
        // $postData['is_expect_finish_order'] =  $params['is_expect_finish_order'] ;//是否根据期望送达时间预约发单（0-否，即时发单；1-是，预约发单），如传1则期望送达时间必传。
        // $postData['expect_finish_time_limit'] =  $params['expect_finish_time_limit'] ;//期望送达时间（单位秒，不早于当前时间）
        // $postData['is_direct_delivery'] =  $params['is_direct_delivery'] ;//是否选择直拿直送（0：不需要；1：需要。选择直拿直送后，同一时间骑士只能配送此订单至完成，同时，也会相应的增加配送费用）


        // $product_list['sku_name'] =  $params['sku_name'] ;//商品名称，限制长度128
        // $product_list['src_product_no'] =  $params['src_product_no'] ;//商品编码，限制长度64
        // $product_list['src_product_no'] =  $params['src_product_no'] ;//商品数量，精确到小数点后两位
        // $product_list['unit'] =  $params['unit'] ;//商品单位，默认：件

        // $postData['product_list'] =  $params['product_list'] ;//订单商品明细
        // $postData['pick_up_pos'] =  $params['pick_up_pos'] ;//货架信息,该字段可在骑士APP订单备注中展示
        // $postData['fetch_code'] =  $params['fetch_code'] ;//取货码，在骑士取货时展示给骑士，门店通过取货码在骑士取货阶段核实骑士
        // $postData['business_type'] =  $params['business_type'] ;//物流配送方向(0-正向送货单、2-售后退货取件单)。如为售后单需传入发货人相关信息(售后场景下发货人一般为顾客，收货人为门店)，并请联系业务经理开通服务
        // $postData['supplier_name'] =  $params['supplier_name'] ;//发货人姓名，订单发货信息默认为门店信息，如需自定义则需传发货人5项信息(发货人姓名、地址、电话、纬度、经度)，并请联系业务经理开通服务
        // $postData['supplier_address'] =  $params['supplier_address'] ;//发货人地址，如不传订单发货信息默认取门店信息
        // $postData['supplier_phone'] =  $params['supplier_phone'] ;//发货人电话，如不传订单发货信息默认取门店信息
        // $postData['supplier_lat'] =  $params['supplier_lat'] ;//发货人纬度，如不传订单发货信息默认取门店信息
        // $postData['supplier_lng'] =  $params['supplier_lng'] ;//发货人经度，如不传订单发货信息默认取门店信息

        // 请求参数
        $postData['shop_no'] =  $params['storeId']??'' ;//配送店铺id
        $postData['origin_id'] =  $params['callNumber']??'' ;//调用方单号
        $postData['cargo_price'] =  $params['cargoPrice']??'' ;//订单金额
        $postData['is_prepay'] =  $params['isPrepay']??'' ;//是否需要垫付 1:是 0:否 (垫付订单金额，非运费)
        $postData['callback'] =  $this->config[ 'notify_url']  ;//回调URL
        $postData['cargo_weight'] =  $params["weight"]??'' ;//订单重量（单位：Kg）

        $postData['receiver_name'] =  $params['receiverList']["toReceiverName"]??'' ;//收货人姓名
        $postData['receiver_address'] =  $params['receiverList']["toAddress"]??'' ;//收货人地址
        $postData['receiver_lat'] =  $params['receiverList']['toLatitude']??'';//收货人地址纬度
        $postData['receiver_lng'] =  $params['receiverList']['toLongitude']??'';//收货人地址经度
        $postData['receiver_phone'] =   $params['receiverList']["toMobile"]??'' ;//收货人手机号（手机号和座机号必填一项）
        $postData['remarks'] =   $params['receiverList']["remarks"]??'' ;//备注

        $postData['supplier_name'] =  $params['sender']["fromSenderName"]??'' ;//发货人姓名，订单发货信息默认为门店信息，如需自定义则需传发货人5项信息(发货人姓名、地址、电话、纬度、经度)，并请联系业务经理开通服务
        $postData['supplier_address'] =  $params['sender']["fromAddress"]??'' ;//发货人地址，如不传订单发货信息默认取门店信息
        $postData['supplier_phone'] =  $params['sender']["fromMobile"]??'' ;//发货人电话，如不传订单发货信息默认取门店信息
        $postData['supplier_lat'] = $params['sender']['fromLatitude']??'' ;//发货人纬度，如不传订单发货信息默认取门店信息
        $postData['supplier_lng'] = $params['sender']['fromLongitude']??'';//发货人经度，如不传订单发货信息默认取门店信息

        $postData['delay_publish_time'] =  !empty($params["appointmentDate"])?strtotime($params["appointmentDate"]):'';//预约发单时间

        $expect_finish_time_limit= $params["expectEndTime"]??'';//期望送达时间（单位秒）
        $postData['expect_finish_time_limit'] =   $expect_finish_time_limit ;//期望送达时间（单位秒）
        $postData['is_expect_finish_order'] =  !empty($expect_finish_time_limit)?1:0;//0-即时发单；1-预约发单

        
        \think\facade\Log::info('达达--订单计费--请求参数---:' . json_encode($postData));
        // dump($postData);exit;

        // 请求达达
        $res = $this->ApiService->sendUnite('orderCalculate',json_encode($postData));
        \think\facade\Log::info('达达--订单计费--请求结果---:' . json_encode($res));
        // dump($res);exit;

        if(isset($res['status'])&&$res['status']==self::STATUS_SUCCESS){
            $appid=$params['appid'];//appid
            $app_type=get_app_type_int($params['app_type']);//app_type
            $data=$res['result'];//请求返回结果
            $third_number=$data['deliveryNo'];//配送单号
            $call_number=$params['callNumber'];//调用方单号

            $appoint_type= $params["appointType"]??"";//0-即时发单；1-预约发单
            $appointment_date= $params["appointmentDate"]??"";//预约发单时间
            $expect_receive_time= $postData['expect_finish_time_limit']??"";//期望送达时间
            $store_id= $params["storeId"]??"";//配送店铺id

            // 新增总订单(总表 金额单位统一：分)
            $orderData['appid'] = $appid;
            $orderData['third_number'] = $third_number;
            $orderData['call_number'] =  $call_number;
            $orderData['app_type'] = $app_type;

            $orderData['appoint_type'] = $appoint_type;//0:立即单, 1:预约单
            $orderData['appointment_date'] = $appointment_date;//预约取件时间
            $orderData['expect_receive_time'] = $expect_receive_time;//期望送达时间
            $orderData['store_id'] = $store_id;//配送店铺ID
           
            $orderData['total_distance'] = $data['distance'] ?? 0;//总距离，单位：米
            $orderData['total_weight'] =  $params['receiverList'][0]["weight"]??'';//总重量，单位：kg
            $orderData['total_amount'] = isset($data['deliverFee'])?yuan_to_fen($data['deliverFee']): 0;//订单总金额，单位：分
            $orderData['coupon_save_fee'] = isset($data['couponFee']) ?yuan_to_fen($data['couponFee']): 0;//优惠的总额度，单位：分
            $orderData['total_fee_after_save'] = isset($data['fee'])?yuan_to_fen($data['fee']): 0;//实际支付的费用，单位：分

            $add_order = (new Order)->orderCreate($orderData);

            $sys_number=$add_order['data']['sys_number'];//骑手系统订单号

            // 新增达达订单(达达 金额单位统一：分)
            $ddOrderData['appid'] = $appid;
            $ddOrderData['third_number'] = $third_number;
            $ddOrderData['sys_number'] = $sys_number;
            $ddOrderData['call_number'] =  $call_number;
            $ddOrderData['app_type'] = $app_type;

            $ddOrderData['appoint_type'] = $appoint_type;//0:立即单, 1:预约单
            $ddOrderData['appointment_date'] = $appointment_date;//预约取件时间
            $ddOrderData['expect_receive_time'] = $appointment_date;//期望送达时间
            $ddOrderData['store_id'] = $store_id;//配送店铺ID

            $ddOrderData['distance'] = $data['distance'] ?? 0;//配送距离(单位：米)
            $ddOrderData['deliverFee'] = isset($data['deliverFee'])?yuan_to_fen($data['deliverFee']): 0;//运费(单位：分)
            $ddOrderData['couponFee'] = isset($data['couponFee']) ?yuan_to_fen($data['couponFee']): 0;//优惠券费用(单位：分)
            $ddOrderData['tips'] = isset($data['tips']) ?yuan_to_fen($data['tips']): 0;//小费（单位：分，精确小数点后一位，小费金额不能高于订单金额。）
            $ddOrderData['fee'] =  isset($data['fee'])?yuan_to_fen($data['fee']): 0;//实际运费(单位：分，运费减去优惠券费用
            $ddOrderData['insuranceFee'] = isset($data['insuranceFee'])?yuan_to_fen($data['insuranceFee']): 0;//保价费(单位：分)
            $add_dd_order = (new OrderDada)->ddOrderCreate($ddOrderData);
            
            // 新增发件人
            $senderData['appid'] = $appid;
            $senderData['third_number'] = $third_number;
            $senderData['sys_number'] = $sys_number;
            $senderData['call_number'] = $call_number;
            $senderData['app_type'] =  $app_type;

            $senderData['from_address'] = $params['sender']['fromAddress'] ?? '';
            $senderData['from_address_detail'] = $params['sender']['fromAddressDetail'] ?? '';
            $senderData['from_sender_name'] = $params['sender']['fromSenderName'] ?? '';
            $senderData['from_mobile'] = $params['sender']['fromMobile'] ?? '';
            $senderData['from_latitude'] = !empty($params['sender']['fromLatitude']) ? floatval($params['sender']['fromLatitude']) : 0;
            $senderData['from_longitude'] = !empty($params['sender']['fromLongitude']) ? floatval($params['sender']['fromLongitude']) : 0;
            $add_sender = (new SenderInfo)->senderCreate($senderData);

            // 新增收件人
            $receiverData['appid'] = $appid;
            $receiverData['third_number'] =$third_number;
            $receiverData['sys_number'] =$sys_number;
            $receiverData['call_number'] =$call_number;
            $receiverData['app_type'] =  $app_type;

            $receive=$params['receiverList']??[];
            $receiverData['to_address'] = $receive['toAddress'] ?? '';
            $receiverData['to_address_detail'] = $receive['toAddressDetail'] ?? '';
            $receiverData['to_latitude'] = !empty($receive['toLatitude']) ? floatval($receive['toLatitude']) : 0;
            $receiverData['to_longitude'] = !empty($receive['toLongitude']) ? floatval($receive['toLongitude']) : 0;
            $receiverData['to_receiver_name'] = $receive['toReceiverName'] ?? '';
            $receiverData['to_mobile'] = $receive['toMobile'] ?? '';

            $add_receiver = (new ReceiverInfo)->receiverCreate($receiverData);


            // Db::startTrans();
            // try {

            //     $add_dd_order = (new OrderDada)->save($ddOrderData);
            //     $add_sender = (new SenderInfo)->senderCreate($senderData);
            //     $add_receiver = (new ReceiverInfo)->receiverCreate($receiverData);

            //     Db::commit();
            // }catch (ValidateException $e) {
            //      Db::rollback();
            // }

            if($add_order['success']){
               $result_data=[
                    "totalDistance"=>$orderData['total_distance'] ,//总距离(米)
                    "totalWeight"=>$orderData['total_weight'] ,//总重量(kg)
                    "sysNumber"=>$sys_number,//系统单号
                    "totalAmount"=> $orderData['total_amount'],//订单总金额(分)
                    "couponSaveFee"=> $orderData['coupon_save_fee'],//优惠的总额度(分)
                    "totalFeeAfterSave"=>$orderData['total_fee_after_save'],//实际支付的费用(分)
                    "order_type"=>'dada'
                ];
               return result_success('success',$result_data);
            }else{
               return result_error($add["msg"]??'保存失败');
            }
        }else{
           return result_error($res["msg"]??'请求失败');
        } 
    }

    // 提交订单（查询运费后下单）
    public function orderPlace($params=[])
    {
        try {
            validate([
                'deliveryNo'  => 'require', 
            ])->message([
                'deliveryNo.require'  => 'deliveryNo必须传递',    
            ])->check($params);
        } catch (ValidateException $e) {
            output_error($e->getError());
        }

         if(strpos($params['app_type'],'pro')){//正式下单
            // 验证余额
            $deal_balance=(new MallDealLog)->where('appid',$params['appid'])->order('id desc')->value('deal_balance');
            if($deal_balance < 3000){
                return result_error('余额不足30元,无法下单');
            }
        }

        $order_status = (new Order)->where('third_number',$params['deliveryNo'])->value('status');
        if($order_status!=0){
            return result_error('已下单，请勿重复下单');
        }

        $data['deliveryNo'] = $params['deliveryNo']??'';
        \think\facade\Log::info('达达--提交订单--请求参数---:' . json_encode($data));

        $res = $this->ApiService->sendUnite('orderPlace',json_encode($data));
        \think\facade\Log::info('达达--提交订单--请求结果---:' . json_encode($res));

         if(isset($res['status'])&&$res['status']==self::STATUS_SUCCESS){
            // 更新总表订单状态
            $orderData['third_number']=$params['deliveryNo'];
            $orderData['status']=self::STATUS_ORDER_DISPATCH;//待接单
            $update_order = (new Order)->orderUpdate($orderData);

            // 更新达达订单状态
            $ddOrderData['third_number']=$params['deliveryNo'];
            $ddOrderData['status']=self::STATUS_ORDER_DISPATCH;//待接单
            $update_ss_order = (new OrderDada)->ddOrderUpdate($ddOrderData);


            if(strpos($params['app_type'],'pro')){//正式下单
                $appid =  $params['appid'] ?? '';
                $deal_type =  get_app_type_int($params['app_type']) ?? '';
                $order_id = $update_order['data']['id']??"";
                $sys_number = $update_order['data']['sys_number']??"";
                $deal_money = $update_order['data']['total_fee_after_save']??"";
                $deal_type_str ="达达下单扣费";

                // 增加扣除账户余额日志
                $dealLogData['appid'] = $appid;//appid
                $dealLogData['deal_type'] =  $deal_type;//交易类型 {radio} (10:闪送, 20:达达,30:蜂鸟,-1充值)
                $dealLogData['order_id'] = $order_id;//order_id
                $dealLogData['sys_number'] = $sys_number;//系统单号
                $dealLogData['deal_money'] = $deal_money;//交易金额，单位：分
                $dealLogData['deal_type_str'] =$deal_type_str;//交易类型说明
                $dealLogData['remark'] ='';//备注
                $add_deal_log=(new MallDealLog)->dealLogCreate($dealLogData);
                if(!$add_deal_log['success']){
                  \think\facade\Log::info('达达--提交订单--余额扣费失败---:' . json_encode($dealLogData));
                  return result_error($add_deal_log['msg']??"余额扣费失败");
                }

                // 扣除账户余额
                $appConfigData['appid'] =$appid;//appid
                $appConfigData['money'] =$deal_money ;//money
                $doBalance=(new AppConfig)->doBalance($appConfigData,-1);

               return result_success('success',[]);
            }
        }else{
           return result_error($res["msg"]??'请求失败');
        } 

    }

    // 7.订单加价(加小费)
    public function addition($params=[])
    {
        try {
            validate([
                'order_id'  => 'require', 
                'additionAmount'  => 'require', 
            ])->message([
                'order_id.require'  => 'order_id必须传递',    
                'additionAmount.require'  => 'additionAmount必须传递',    
            ])->check($params);
        } catch (ValidateException $e) {
            output_error($e->getError());
        }
        $call_number = (new Order)->where('third_number',$params['order_id'])->value('call_number');
        if(!$call_number){
            output_error('未查询到订单');
        }

        $postData['order_id']=  $call_number;
        $postData['tips']  =  fen_to_yuan($params['additionAmount']);//传分 要元
 
        $saveData['third_number'] = $params['order_id'];
        $saveData['addition_amount'] =  $params['additionAmount'];
        \think\facade\Log::info('达达--订单加价--请求参数---:' . json_encode($postData));
        // var_dump($postData);exit;

        $res = $this->ApiService->sendUnite('addition',$postData);
        \think\facade\Log::info('达达--订单加价--请求结果---:' . json_encode($res));
        // var_dump($res);exit;


        if(isset($res['status'])&&$res['status']==self::STATUS_SUCCESS){
            $Order = new Order();
            $add = $Order->additionSave($saveData);

            $Order = new OrderDada();
            $add = $Order->ddAdditionSave($saveData);
            if($add['success']){
               return result_success('success',[]);
            }else{
               return result_error($add["msg"]??'保存失败');
            }
        }else{
           return result_error($res["msg"]??'请求失败');
        } 

    }

    // 8.查询订单详情
    public function orderInfo($params=[])
    {
         try {
            validate([
                'order_id'  => 'require', 
            ])->message([
                'order_id.require'  => 'order_id必须传递',    
            ])->check($params);
        } catch (ValidateException $e) {
            output_error($e->getError());
        }

        $apiData['order_id'] =  $params['order_id'];
        $dist['method']='orderInfo';
        $apiData = json_encode(array_filter($apiData));
        $res = $this->ApiService->sendUnite($dist['method'],$apiData);

        if(isset($res['status'])&&$res['status']==self::STATUS_SUCCESS){
            $data=$res['result'];

            // 骑手信息
            $courier['name']=$data['transporterName'];//骑手姓名
            $courier['mobile']=$data['transporterPhone'];//骑手电话
            $courier['latitude']=$data['transporterLng'];//骑手经度
            $courier['longitude']=$data['transporterLat'];//骑手纬度
            $courier['headIcon']='https://xyh-static-app.oss-cn-hangzhou.aliyuncs.com/static/icon/rider-headIcon.png';//骑手头像

            $dadaStatusList = Order::getDadaStatusConver();
            $statusCode=  $dadaStatusList[$data['statusCode']] ?? 0;//订单状态

            $result = [
                "orderStatus"=> $statusCode,//订单状态
                "orderStatusDesc"=>$data['statusMsg'],//订单状态描述
                "courier"=>$courier,//骑手信息
                "totalAmount"=>yuan_to_fen($data['deliveryFee']??0),//订单总金额(元转分)
                "couponSaveFee"=>yuan_to_fen($data['couponFee']??0),//总优惠额度(元转分)
                "totalFeeAfterSave"=>yuan_to_fen($data['actualFee']??0)//实付金额(元转分)
            ];

            return result_success('success', $result);
        }else{
           return result_error($res["msg"]??'请求失败');
        } 
    }

    // 10.查询订单续重加价金额
    public function calculateOrderAddWeightFee($params=[])
    {
       return result_error("达达不支持");
    }

    // 11.支付订单续重费用
    public function payAddWeightFee($params=[])
    {
       return result_error("达达不支持");
    }

    // 12.订单预取消
    public function preAbortOrder($params=[])
    {
        return result_error("达达不支持");
    }

    // 13.订单取消
    public function abortOrder($params=[])
    {
        //region  参数验证
        try {
            validate([
                'order_id'  => 'require',
                'operationType' => 'require'
            ])->message([
                'order_id.require'  => '第三方订单号必须传递',
                'operationType.require'  => '操作类型必须传递',
            ])->check($params);

            //达达 区分订单取消\追加取消接口
            $dist['method']='abortOrder';

            // 默认值为1订单取消，2追加订单取消
            $dist['type'] = $params['operationType'];
            if($dist['type']==1)
            {
                if($params['cancelReasonId']== 1000)
                    validate([
                        'cancelReason'  => 'require',
                        'cancelReasonId'  => 'require',
                    ])->message([
                        'cancelReason.require'  => '取消原因必须传递',
                        'cancelReasonId.require'  => '取消原因ID必须传递',
                    ])->check($params);
            }

        } catch (ValidateException $e) {
            output_error($e->getError());
        }
        //endregion

        //region 达达 订单取消
        if($dist['type']==1) {
            $apiData['order_id'] = $params['order_id'];
            $apiData['cancel_reason_id'] = $params['cancelReasonId'];

            if ($apiData['cancel_reason_id'] == 1000)
                $apiData['cancel_reason'] = $params['cancelReason'];
        }
        else {
            $apiData['order_id'] = $params['order_id'];
            $dist['method'] = 'cancelAppendOrder';
        }

        $apiData = json_encode(array_filter($apiData));

        $res = $this->ApiService->sendUnite($dist['method'],$apiData);
        \think\facade\Log::info('达达--订单取消--请求返回结果---:' . json_encode($res));
        //endregion

        if(isset($res['status']) && $res['status']==self::STATUS_SUCCESS){
            //region 达达 平台取消成功后，同步修改订单状态
            $Order = new Order();
            $orderUpdate['call_number'] = $params['order_id'];
            $orderUpdate['status'] = self::STATUS_ORDER_CANCELLED;
            $add = $Order->orderUpdate($orderUpdate);

            $OrderDada = new OrderDada();
            $orderUpdate['call_number'] = $params['order_id'];
            $orderUpdate['status'] = self::STATUS_ORDER_CANCELLED;
            $add = $OrderDada->ddOrderUpdate($orderUpdate);

            if($add['success']){
                //返回骑手订单扣费deductFee：扣除费，sendBackFee：退回费,单位为分
                $resData['deductFee']=isset($res['result']['deduct_fee'])?yuan_to_fen($res['result']['deduct_fee']): 0;//达达单位为元 统一转为分
                $resData['sendBackFee'] = 0;
               return result_success('success',$resData);
            }else{
               return result_error($add["msg"]??'保存失败');
            }
            //endregion
        }else{
           return result_error($res["msg"]??'请求失败');
        } 
    }

    // 17.查询账号额度
    public function getUserAccount($params=[])
    {
        $res = $this->ApiService->sendUnite('getUserAccount');

        if(isset($res['status'])&&$res['status']==self::STATUS_SUCCESS){
            $res["result"]=['balance'=>$res["result"]["deliverBalance"]];
        }

        return $this->ApiService->returnUnite($res);
    }

    public function statusNotify($param=[])
    {
        if(empty($param['order_id'])){
            \think\facade\Log::error("达达订单号为空:".json_encode($param));
            return json_encode(["status"=>self::DADA_STATUS_ERROR,"msg"=>"","data"=>null]);
        }
        $where['call_number'] = $param['order_id'];
        $where['app_type'] = $param['app_type'];
        $orderdetail =Order::where($where)->order('id', 'desc')->find();

        $appid = $orderdetail['appid'] ?? '';
        if (!empty($appid)){
            $notify_url = Db::name("app_interface_config")
                ->where('appid', $appid)
                ->value('rider_notify');
        }

        if (empty($notify_url)){
            \think\facade\Log::error("回调地址不存在:".json_encode($param));
            return json_encode(["status"=>self::DADA_STATUS_ERROR,"msg"=>"","data"=>null]);
        }
        $param['issOrderNo'] = $orderdetail['third_number'] ?? '';
        $param['orderNo'] = $orderdetail['call_number'] ?? '';
        $param['third_number'] = $orderdetail['third_number'] ?? '';//第三方配送平台订单号
        $param['sys_number'] = $orderdetail['sys_number'] ?? '';//系统订单号(系统生成)
        $param['call_number'] = $orderdetail['call_number'] ?? '';//调用方订单号
        $param['appid'] = $orderdetail['appid'] ?? '';//appid
        $param['app_type'] = $orderdetail['app_type'] ?? 0;

        //更新配送员消息
        if (!empty($param['dm_id'])){
            $Courier = new Courier();
            $courierParam = $param;
            $courierParam['third_number'] = $orderdetail['third_number'] ?? '';//第三方配送平台订单号
            $courierParam['sys_number'] = $orderdetail['sys_number'] ?? '';//系统订单号(系统生成)
            $courierParam['call_number'] = $orderdetail['call_number'] ?? '';//调用方订单号
            $courierParam['appid'] = $orderdetail['appid'] ?? '';//appid
            $courierParam['app_type'] = $orderdetail['app_type'] ?? 0;
            $courierParam['rider_id'] = $param['dm_id'] ?? 0;
            $courierParam['name'] = $param['dm_name'] ?? '';
            $courierParam['mobile'] = $param['dm_mobile'] ?? '';
            $courierParam['finish_code'] = $param['finish_code'] ?? '';
            $courierParam = camelToSnake($courierParam);
            $courier_res = $Courier->courierSave($courierParam);
            if(!$courier_res["success"]){
                \think\facade\Log::error("闪送配送员保存失败:".json_encode($courierParam)."闪送订单更新结果:".json_encode($courier_res));
            }
        }
        //更新订单基本信息
        $Order = new Order();

        if (!empty($param['order_status'])){
            $dadaStatusList = Order::getDadaStatusConver();
            $param['status'] =  $dadaStatusList[$param['order_status']] ?? 0;//订单状态
            $dadaStatusStrList = Order::getDadaStatusStr();
            $param['statusDesc'] =  $dadaStatusStrList[$param['order_status']] ?? 0;//订单状态
            $param['subStatus'] =  $param['status'];
            $param['subStatusDesc'] =  $param['statusDesc'];
        }
        if (!empty($param['cancel_from'])) {
            $dadaCancelReasonList = Order::getDadaCancelReasonConver();
            $param['abort_type'] = $dadaCancelReasonList[$param['cancel_from']] ?? '';//订单取消类型
        }
        if (!empty($courier_res["data"])){
            $param['courier_id'] = $courier_res["data"];
        }
        $param['abort_reason'] =  $param['cancel_reason']??'' ;

        $orderParam = camelToSnake($param);
        $res_order = $Order->orderUpdate($orderParam);
        if(!$res_order["success"]){
            \think\facade\Log::error("闪送订单基本信息保存失败:".json_encode($orderParam)."闪送订单基本信息更新结果:".json_encode($res_order));
        }
        //更新闪送订单表
        $OrderShansong = new OrderDada();
        $res_order_shangsong = $OrderShansong->ddOrderUpdate($orderParam);
        if(!$res_order_shangsong["success"]){
            \think\facade\Log::error("闪送订单更新失败:".json_encode($orderParam)."闪送订单更新结果:".json_encode($res_order_shangsong));
        }

        //转发到终端平台
        $param = snakeToCamel($param);
        $res = curl_post($notify_url, $param);
        $res = json_decode($res,1);

        $msg = !empty($res) && isset($res['msg']) ? $res['msg'] : '';
        if (empty($res) || empty($res['status'])) {
            return json_encode(["status"=>self::DADA_STATUS_ERROR,"msg"=>$msg,"data"=>null]);
        }
        return json_encode(["status"=>self::DADA_STATUS_SUCCESS,"msg"=>$msg,"data"=>null]);
    }

    // 19.修改收件人手机号
    public function updateToMobile($params=[])
    {
      return result_error("达达不支持");
    }

    // 21.查询订单ETA
    public function orderEta($params=[])
    {
       return result_error("达达不支持");
    }

    // 22.订单追单
    public function appendOrder($params=[])
    {
        //region  参数验证
        try {
            validate([
                'sysNumber'  => 'require',
                'appendsysNumber'  => 'require',
                'transporterId'  => 'require',
                'shopNo' => 'require',
            ])->message([
                'sysNumber.require'  => 'sysNumber必须传递',
                'appendsysNumber.require'  => 'appendsysNumber必须传递',
                'transporterId.require'  => 'transporterId必须传递',
                'shopNo.require'  => 'shopNo必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            output_error($e->getError());
        }
        //endregion

        //region 达达 订单追加
        $dist['method']='appendOrder';
        $appendsysNumber=Order::where('sys_number',$params['appendsysNumber'])->value('call_number');
        $apiData['order_id'] = $appendsysNumber;
        $apiData['transporter_id'] = $params['transporterId'];
        $apiData['shop_no'] = $params['shopNo'];

        $apiData = json_encode(array_filter($apiData));
        $res = $this->ApiService->sendUnite($dist['method'],$apiData);
        //endregion

        if(isset($res['status']) && $res['status']==self::STATUS_SUCCESS){
            //region 达达 平台取消成功后，同步修改订单状态
            $Order = new Order();
            $res['data']['orderNumber'] = $apiData['order_id'];
            $res['data']['status'] = self::STATUS_ORDER_CANCELLED;
            $add = $Order->orderUpdate($res['data']);
            if($add['success']){
                return result_success('success',[]);
            }else{
                return result_error($add["msg"]??'保存失败');
            }
            //endregion
        }else{
            return result_error($res["msg"]??'请求失败');
        }
    }

    // 23.查询是否支持尊享送
    public function qualityDeliverySwitch($params=[])
    {
      return result_error("达达不支持");
    }

    // 24.查询尊享送达成状态
    public function qualityDeliveryStatus($params=[])
    {
      return result_error("达达不支持");
    }

    /**
     * 商户确认物品已返还
     * @param $params
     * @return array
     */
    public function confirmGoodsReturn($params=[]) : array
    {
        try {
            validate([
                'order_id'  => 'require',
            ])->only(['order_id'])->message([
                'order_id.require'  => '订单号必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            return result_error($e->getError());
        }
        $data['order_id']=$params['order_id'];
        $res = $this->ApiService->sendUnite('confirmGoodsReturn',json_encode($data,JSON_UNESCAPED_UNICODE));
        return $this->ApiService->returnUnite($res);
    }

    /**
     * 商户审核骑士取消订单
     * @param array $params
     * @return array
     */
    public function merchantExamine(array $params=[]) : array
    {
        try {
            validate([
                'mesID'  => 'require',
                'isConfirm'  => 'require',
            ])->only(['mesID','isConfirm','imgs','rejectReason'])->message([
                'mesID.require'  => '消息ID必须传递',
                'isConfirm.require'  => '审核结果必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            return result_error($e->getError());
        }
        $message=Db::name('message')->where('id',$params['mesID'])->find();
        if(!$message) output_error('消息不存在');
        $info=json_decode($message['content'],true);
        $data=[
            'messageBody'=>[
                'orderId'=>$info['orderId'],
                'dadaOrderId'=>$info['dadaOrderId'],
                'isConfirm'=>$params['isConfirm'],
                'imgs'=>$params['imgs'] ?? [],
                'rejectReason'=>$params['rejectReason'] ?? ''
            ],
            'messageType'=>1
        ];
        $res = $this->ApiService->sendUnite('merchantExamine',$data);
        return $this->ApiService->returnUnite($res);
    }

    /**
     * 查询骑士位置
     * @param array $params
     * @return array
     */
    public function courierInfo($params=[]) : array
    {
        try {
            validate([
                'order_id'  => 'require',
            ])->only(['order_id'])->message([
                'order_id.require'  => '订单号必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            return result_error($e->getError());
        }
        $data['orderIds']=explode(',',$params['order_id']);
        $res = $this->ApiService->sendUnite('courierInfo',json_encode($data,JSON_UNESCAPED_UNICODE));
        return $this->ApiService->returnUnite($res);
    }

    /**
     * 获取骑士配送信息H5页面
     * @param array $params
     * @return array
     */
    public function transporter(array $params=[]) : array
    {
        try {
            validate([
                'order_id'  => 'require',
            ])->only(['order_id'])->message([
                'order_id.require'  => '订单号必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            return result_error($e->getError());
        }
        $res = $this->ApiService->sendUnite('transporter',json_encode($params,JSON_UNESCAPED_UNICODE));
        return $this->ApiService->returnUnite($res);
    }

    /**
     * 更新取件码和货架号
     * @param array $params
     * @return array
     */
    public function fetchCode(array $params=[]) : array
    {
        try {
            validate([
                'originId'  => 'require',
            ])->only(['originId','type','fetchCode','shelfCode'])
            ->message([
                'originId.require'  => '三方单号必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            return result_error($e->getError());
        }
        $data['type']=$params['type'] ?? 1;
        $data['fetchCode']=$params['fetchCode'] ?? null;
        $data['shelfCode']=$params['shelfCode'] ? explode(',',$params['shelfCode']) : null;
        $data['originId']=$params['originId'];
        $res = $this->ApiService->sendUnite('fetchCode',json_encode($data,JSON_UNESCAPED_UNICODE));
        if('success'===$res['status'])
        {
            //todo 修改订单扩展信息
            return result_success('success');
        }
        return result_error($res['msg']);
    }

    /**
     * 商户确认售后单交接完成
     * @param array $params
     * @return array
     */
    public function afterSale(array $params=[]) : array
    {
        try {
            validate([
                'order_id'  => 'require',
            ])->only(['order_id'])->message([
                'order_id.require'  => '订单号必须传递',
            ])->check($params);
        } catch (ValidateException $e) {
            return result_error($e->getError());
        }
        $res = $this->ApiService->sendUnite('afterSale',json_encode($params,JSON_UNESCAPED_UNICODE));
        if('success'===$res['status'])
        {
            //todo 订单售后记录完善，修改订单状态
            return result_success('success');
        }
        return result_error($res['msg']);
    }
}